{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Вопросы для повторения:**\n",
    "\n",
    "* Что такое функтор? Что такое лямбда?\n",
    "\n",
    "* Что здесь происходит?\n",
    "\n",
    "```c++\n",
    "auto make_age_less_filter(int x)\n",
    "{\n",
    "    return [&x](const Person& person){ return person.age < x; };\n",
    "}\n",
    "\n",
    "std::copy_if(people.begin(),\n",
    "             people.end(),\n",
    "             make_age_less_filter(33),\n",
    "             std::ostream_iterator<Person>(std::cout, \"\\n\"));\n",
    "```\n",
    "\n",
    "* Что здесь происходит? Всё ли в порядке?\n",
    "\n",
    "```c++\n",
    "unsigned compare_count = 0;\n",
    "std::sort(v.begin(), v.end(),\n",
    "          [&](const auto& lhs, const auto& rhs){\n",
    "              ++compare_count;\n",
    "              return lhs < rhs;\n",
    "          });\n",
    "```\n",
    "\n",
    "* Понять что происходит, исправить ошибки и упростить:\n",
    "\n",
    "```c++\n",
    "struct Person\n",
    "{\n",
    "  std::string name;\n",
    "  int age;\n",
    "};\n",
    "\n",
    "int function(std::vector<Persion> people)\n",
    "{\n",
    "  auto tmp = people;\n",
    "  \n",
    "  std::remove_if(tmp.begin(), tmp.end(), [](const Person& p){\n",
    "    return p.age < 33;\n",
    "  });\n",
    "\n",
    "  std::sort(tmp.begin(), tmp.end(), [](const Person& lhs, const Person& rhs){\n",
    "    reutrn lhs.age < rhs.age;\n",
    "  });\n",
    "\n",
    "  auto it = std::find_if(tmp.rbegin(), tmp.rend(), [](const Person& p){\n",
    "    return p.name == \"Fedor\";\n",
    "  });\n",
    "\n",
    "  return it->age;\n",
    "}\n",
    "```\n",
    "\n",
    "* Понять что происходит, исправить ошибки и упростить:\n",
    "\n",
    "```c++\n",
    "std::set<int, int> function(const std::vector<Person>& people)\n",
    "{\n",
    "  std::map<int, std::vector<std::string>> age_to_names;\n",
    "  for (const auto& p : people)\n",
    "    age_to_names[p.age].push_back(p.name);\n",
    "\n",
    "  for (auto& age_and_names : age_to_names)\n",
    "  {\n",
    "    auto names = age_and_names.second;\n",
    "    std::sort(names.begin(), names.end());\n",
    "  }\n",
    "\n",
    "  std::set<int, int> rv;\n",
    "  for (auto& age_and_names : age_to_names)\n",
    "    rv[age_and_names.first] = age_and_names.second.size();\n",
    "    \n",
    "  return rv;\n",
    "}\n",
    "```\n",
    "\n",
    "* Понять что происходит, исправить ошибки и упростить:\n",
    "\n",
    "```c++\n",
    "\n",
    "std::set<int, int> function(const std::vector<Person>& people)\n",
    "{\n",
    "  std::map<int, std::vector<std::string>> age_to_names;\n",
    "  for (const auto& p : people)\n",
    "    age_to_names[p.age].push_back(p.name);\n",
    "\n",
    "  for (auto& age_and_names : age_to_names)\n",
    "  {\n",
    "    auto names = age_and_names.second;\n",
    "    std::sort(names.begin(), names.end());\n",
    "  }\n",
    "\n",
    "  std::set<int, int> rv;\n",
    "  for (auto& age_and_names : age_to_names)\n",
    "    rv[age_and_names.first] = age_and_names.second.size();\n",
    "    \n",
    "  return rv;\n",
    "}\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "**Долг с прошлой лекции:**\n",
    "* Если вы пишете алгоритм, и вам кажется, что он достаточно общий, значит, алгоритм до вас уже кто-то реализовывал, загляните в STL, скорее всего, он там уже есть.\n",
    "* [toupper && unsigned chars](https://en.cppreference.com/w/cpp/string/byte/toupper)\n",
    "* Примеры применения immediately call lambdas:\n",
    "\n",
    "Вариант 1: inplace инициализация полей класса\n",
    "\n",
    "```c++\n",
    "class NetworkSystem\n",
    "{\n",
    "private:\n",
    "    NetworkConfig config_;\n",
    "    \n",
    "public:\n",
    "    NetworkSystem(const std::string& config_filename)\n",
    "        : config_([](){\n",
    "            const auto json = read_json(config_filename);\n",
    "            \n",
    "            NetworkConfig cfg;\n",
    "            cfg.http_timeout = json['http']['timeout'];\n",
    "            cfg.retry_count = json['retry_count'];\n",
    "            return cfg;\n",
    "          }())\n",
    "    {\n",
    "    }\n",
    "            \n",
    "   ...    \n",
    "};\n",
    "```\n",
    "\n",
    "\n",
    "Вариант 2: inplace инициализация static-переменных\n",
    "\n",
    "```c++\n",
    "log4cplus::Logger& getDefaultLogger()\n",
    "{\n",
    "  static log4cplus::Logger s_log = [] {\n",
    "    auto log = log4cplus::Logger::getInstance(L\"default\");\n",
    "    // setup log properties here\n",
    "    return log;\n",
    "  }();\n",
    "\n",
    "  return s_log;\n",
    "}\n",
    "```\n",
    "\n",
    "\n",
    "Вариант 3:\n",
    "\n",
    "```c++\n",
    "void process_logs(const std::string& logs_filename, const Date& min_date)\n",
    "{\n",
    "    // initialize const records,\n",
    "    // cleanup init harness on completion\n",
    "    const auto log_recods = [&](){\n",
    "        std::ifstream ifs(logs_filename);\n",
    "        if (!ifs)\n",
    "            throw std::runtime_error(\"filed to open log file: \" + logs_filename);\n",
    "        \n",
    "        std::vector<LogRecord> records{std::istream_iterator(ifs),\n",
    "                                       std::istream_iterator()};\n",
    "        boost::remove_erase_if(records,\n",
    "                               [&](const auto& rec) { return rec.date < min_date; });\n",
    "        return records;\n",
    "    }();\n",
    "    \n",
    "    // further const records processing\n",
    "    ...\n",
    "}\n",
    "```\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
